package com.ybear.ybutils.utils

import com.ybear.ybutils.utils.handler.HandlerManage
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.core.Observer
import io.reactivex.rxjava3.core.Scheduler
import io.reactivex.rxjava3.disposables.Disposable
import io.reactivex.rxjava3.schedulers.Schedulers
import java.util.concurrent.CopyOnWriteArrayList

/**
 * 数据观察者管理器 - DataObserverManage
 * 通过 setResult 设置一个通知，它会将设置的通知回调给注册者，即 registerResult
 */
open class DOM private constructor() {
    companion object {
        @JvmStatic
        private val i: DOM by lazy { DOM() }
        @JvmStatic
        fun getInstance(): DOM { return i }
    }

    interface OnResultListener {
        fun onResult(id: Int, data: Any?)
    }
    private interface OnObserverResultCall {
        fun onSuccess(l: OnResultListener)
        fun onFail(message: String?, e: Throwable)
    }
    private val mHandler = HandlerManage.create()
    private val listenerList: MutableList<OnResultListener> = CopyOnWriteArrayList()

    @Synchronized
    private fun setResultByObs(id: Int, data: Any?, scheduler: Scheduler) {
        observable( scheduler, object : OnObserverResultCall {
            override fun onSuccess(l: OnResultListener) {
                l.onResult( id, data )
            }

            override fun onFail(message: String?, e: Throwable) {
                TODO("Not yet implemented")
            }
        })
    }

    /**
     * 设置处理结果（在 OnResultListener 监听器中回调）
     * @param id        监听的id
     * @param data      数据源
     */
    @Synchronized
    fun setResult(id: Int, data: Any?) {
        listenerList.forEach { it.onResult( id, data ) }
    }

    /**
     * 设置处理结果（在 OnResultListener 监听器中回调）
     * @param id            监听的id
     * @param data          数据源
     * @param delayMillis   延迟处理
     */
    @Synchronized
    fun setResult(id: Int, data: Any?, delayMillis: Long) {
        mHandler.postDelayed( { setResult( id, data ) }, delayMillis )
    }

    /**
     * 设置处理结果（在 OnResultListener 监听器中回调）
     * @param id            监听的id
     * @param data          数据源
     */
    @Synchronized
    fun setResult(id: Int) { setResult( id, null ) }

    /**
     * 设置处理结果（在 OnResultListener 监听器中回调）
     * * 监听器会在线程中调用，对于监听器中存在View处理时，可能会导致闪退
     * @param id        监听的id
     * @param data      数据源
     */
    @Synchronized
    fun setResultByIO(id: Int, data: Any?) {
        setResultByObs( id, data, Schedulers.io() )
    }
    /**
     * 设置处理结果（在 OnResultListener 监听器中回调）
     * * 监听器会在线程中调用，对于监听器中存在View处理时，可能会导致闪退
     * @param id            监听的id
     * @param data          数据源
     * @param delayMillis   延迟处理
     */
    @Synchronized
    fun setResultByIO(id: Int, data: Any?, delayMillis: Long) {
        mHandler.postDelayed( { setResultByIO( id, data ) }, delayMillis )
    }

    /**
     * 设置处理结果（在 OnResultListener 监听器中回调）
     * * 监听器会在线程中调用，对于监听器中存在View处理时，可能会导致闪退
     * @param id            监听的id
     */
    @Synchronized
    fun setResultByIO(id: Int) { setResultByIO(id, null) }

    /**
     * 设置处理结果（在 OnResultListener 监听器中回调）
     * * 监听器会在主线程中调用，对于监听器中存在View处理时，不会引起闪退。
     * * 注册大量监听器时，设置处理结果可能会引起卡顿
     * @param id            监听的id
     * @param data          数据源
     */
    @Synchronized
    fun setResultByPost(id: Int, data: Any?) {
        setResultByObs( id, data, AndroidSchedulers.mainThread() )
    }
    /**
     * 设置处理结果（在 OnResultListener 监听器中回调）
     * * 监听器会在主线程中调用，对于监听器中存在View处理时，不会引起闪退。
     * * 注册大量监听器时，设置处理结果可能会引起卡顿
     * @param id            监听的id
     * @param data          数据源
     * @param delayMillis   延迟处理
     */
    @Synchronized
    fun setResultByPost(id: Int, data: Any?, delayMillis: Long) {
        mHandler.postDelayed( { setResultByPost( id, data ) }, delayMillis )
    }

    /**
     * 设置处理结果（在 OnResultListener 监听器中回调）
     * * 监听器会在主线程中调用，对于监听器中存在View处理时，不会引起闪退。
     * * 注册大量监听器时，设置处理结果可能会引起卡顿
     * @param id            监听的id
     */
    @Synchronized
    fun setResultByPost(id: Int) { setResultByPost(id, null) }

    /**
     * 注册监听器
     * @param mOnResultListener     注册的监听器
     * @return                      是否注册成功
     */
    fun registerResult(mOnResultListener: OnResultListener): Boolean {
        return listenerList.add(mOnResultListener)
    }

    /**
     * 解除注册监听器
     * @param mOnResultListener     解除的监听器
     * @return                      是否解除成功
     */
    fun unRegisterResult(mOnResultListener: OnResultListener): Boolean {
        return listenerList.remove(mOnResultListener)
    }

    fun clear() {
        listenerList.clear()
    }

    private fun observable(scheduler: Scheduler, call: OnObserverResultCall) {
        Observable.fromArray( *listenerList.toTypedArray() )
            .subscribeOn( Schedulers.io() )
            .observeOn( scheduler )
            .unsubscribeOn( scheduler )
            .subscribe(object : Observer<OnResultListener> {
                override fun onSubscribe(d: Disposable) {}
                override fun onNext(l: OnResultListener) {
                    try {
                        call.onSuccess( l )
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }
                override fun onError(e: Throwable) {
                    try {
                        call.onFail( e.message, e )
                    } catch (ex: Exception) {
                        ex.printStackTrace()
                    }
                }
                override fun onComplete() {}
            })
    }
}